/*
 * FileBasedDocumentManager.java is part of htn-core.
 *
 * FileBasedDocumentManager.java is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FileBasedDocumentManager.java is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FileBasedDocumentManager.java.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.htn.repository;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.Vector;

import org.htn.plugin.PluginExecutor;
import org.htn.rtml.RTMLHelperBean;
import org.htn.rtml.RTMLMode;

public class FileBasedDocumentManager extends AbstractDocumentManager<Object>
{
	private static final String FILENAME_BASE="~/db/";
	private Vector<String> knownDocs;
	
	public FileBasedDocumentManager()
	{
		// Read in all files and store in vector.
		File dirListing = new File(FILENAME_BASE);
		knownDocs = new Vector<String>();
		if (dirListing.isDirectory())
		{
			String[] listing = dirListing.list();
			for (int i=0; i< listing.length; i++)
			{
				knownDocs.add(listing[i]);
			}
		}
	}
	
	public Object persist(Object rtml) throws DocumentManagerException 
	{
		String rtmlString = null;
		
		// Check incoming rtml is a string
		if (rtml instanceof String) 
		{
			rtmlString = (String) rtml;	
		}
		else
		{
			throw new DocumentManagerException();
		}
		
		// Generate an id from rtml
		String oid = generateId(rtmlString);
		
		// Check vector to see if we already know this doc
		Boolean known = knownDocs.contains(oid);
		
		// XML helpers to enable manipulation of rtml tags.
		RTMLHelperBean helper = new RTMLHelperBean();
		RTMLMode mode = helper.getMode((String)rtml);
		
		//
		// If message is an update then
		//
		if (mode == RTMLMode.UPDATE && known)
		{
			// Update rtml
			String existingRTML = null;
			existingRTML = read(oid);

			//TODO Merge new data with old.
			Set<String> uris = helper.getImagedataUriSet(rtmlString);
			
			String updatedRTML = null;

			// trigger plugins
			updatedRTML = triggerPlugins(existingRTML);

			//TODO Merge post plugin rtml with updated rtml.

			// Persist
			write(oid, updatedRTML);
			
			// Trigger update to user agent
			triggerUpdate(updatedRTML);
		}
		//
		// else message is new
		//
		else if (mode == RTMLMode.REQUEST)
		{
			// Persist
			write(oid, rtmlString);

			// add doc to vector of known docs
			knownDocs.add(oid);
		}
		//
		// else message is complete
		//
		else if (mode == RTMLMode.COMPLETE)
		{
			
			//Update rtml 
			String updatedRTML = null;

			//Trigger plugins
			updatedRTML = triggerPlugins(rtmlString);
			
			// Persist
			write(oid, updatedRTML);
	
			// Trigger complete to user agent
			triggerCompleted(updatedRTML);
		}
		
		// return id
		return oid;
	}

	/**
	 * 
	 * @param existingRTML
	 * @return
	 */
	private String triggerPlugins(String existingRTML) 
	{
		// No plugins for this implementation.
		return existingRTML;
	}

	private void triggerUpdate(String updatedRTML) 
	{
	
		// NOT DONE FOR THIS IMPLEMENTATION
		
	}

	private void triggerCompleted(String updatedRTML) 
	{
	
		// NOT DONE FOR THIS IMPLEMENTATION
		
	}
	
	/**
	 * 
	 * @param existingFile
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private String read(String fileName) 
	{
		File file = new File(fileName);
		if (!file.exists())
		{
			try 
			{
				throw new FileNotFoundException();
			} 
			catch (FileNotFoundException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		FileInputStream input;
		byte b[]= null;
		try 
		{
			input = new FileInputStream(file);
			int x= input.available();
			b = new byte[x];
			input.read(b);
			input.close();
			input = null;
		} 
		catch (FileNotFoundException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new String(b);
	}

	/**
	 * 
	 * @param existingFile
	 * @param updatedRTML
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void write(String file, String RTML)
	{
		try 
		{
			FileOutputStream output = new FileOutputStream(new File(file));
			byte b[] = RTML.getBytes();
			output.write(b);
			output.close();
			output = null;
		} 
		catch (FileNotFoundException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}			
	}

	/**
	 * 
	 */
	public Object query(String id) throws DocumentManagerException 
	{
		if (id == null)
		{
			throw new DocumentManagerException();
		}
		File existingFile = new File(id);
		String existingRTML = null;
		
		// Check vector to see if we already know this doc
		Boolean known = knownDocs.contains(id);

		// Get RTML		
		if (known && existingFile.exists())
		{
			try 
			{
				FileInputStream input = new FileInputStream(existingFile);
				int x= input.available();
				byte b[]= new byte[x];
				input.read(b);
				existingRTML = new String(b);
			} 
			catch (FileNotFoundException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		if (existingRTML == null)
		{
			throw new DocumentManagerException();
		}
		
		return existingRTML;
	}

	private String generateId(String rtml) 
	{
		//Create a RTML helper
		RTMLHelperBean helperBean = new RTMLHelperBean();
		
		//Extract OIDs from RTML inorder to build a unique id for rtml document.
		
		return FILENAME_BASE + "/" +
		(String) helperBean.getContactUsername(rtml).toArray()[0] + "/" +
		(String) helperBean.getProjectID(rtml) + "/" +
		(String) helperBean.getRTMLUid(rtml) + "/" +
		(String) helperBean.getTargetId(rtml);
		
		
	}
}
